package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.binary.core.util.BinaryUtils;
import com.google.common.collect.Lists;
import com.uinnova.product.eam.base.exception.ServerException;
import com.uinnova.product.eam.base.local.TaskFromWorkflowContext;
import com.uinnova.product.eam.base.local.TaskFromWorkflowContextValue;
import com.uinnova.product.eam.base.util.EamUtil;
import com.uinnova.product.eam.comm.diagram.DiagramReviewInfo;
import com.uinnova.product.eam.comm.diagram.DiagramReviewState;
import com.uinnova.product.eam.comm.model.es.*;
import com.uinnova.product.eam.feign.workable.FlowableFeign;
import com.uinnova.product.eam.feign.workable.entity.*;
import com.uinnova.product.eam.model.EamArtifactVo;
import com.uinnova.product.eam.model.bm.CategoryNode;
import com.uinnova.product.eam.model.bm.SimpDiagramInfo;
import com.uinnova.product.eam.model.cj.domain.PlanDesignInstance;
import com.uinnova.product.eam.model.constants.FlowableConstant;
import com.uinnova.product.eam.model.dto.ApproveParam;
import com.uinnova.product.eam.model.enums.AssetType;
import com.uinnova.product.eam.model.enums.CategoryTypeEnum;
import com.uinnova.product.eam.model.enums.ModelProcessTypeEnum;
import com.uinnova.product.eam.service.*;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.cj.dao.PlanDesignInstanceDao;
import com.uinnova.product.eam.service.es.AssetWarehouseDirDao;
import com.uinnova.product.eam.service.es.DiagramApproveRltDao;
import com.uinnova.product.eam.service.es.DiagramReviewInfoDao;
import com.uinnova.product.eam.service.fx.ProcessDiagramSvc;
import com.uinnova.project.api.diagram.v2.client.ESDiagramApiClient;
import com.uinnova.project.base.diagram.comm.model.ESDiagram;
import com.uinnova.project.base.diagram.comm.model.ESDiagramDTO;
import com.uinnova.project.base.diagram.comm.model.ESDiagramInfoDTO;
import com.uinnova.project.db.eam.ESDiagramDao;
import com.uinnova.project.service.eam.ESDiagramSvc;
import com.uino.api.client.permission.IOrgApiSvc;
import com.uino.api.client.permission.IRoleApiSvc;
import com.uino.bean.cmdb.base.ESCIInfo;
import com.uino.bean.cmdb.base.LibType;
import com.uino.bean.permission.base.SysOrg;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.base.TypeVo;
import com.uino.bean.permission.business.CurrentUserInfo;
import com.uino.bean.permission.business.UserInfo;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.permission.rlt.ESRoleModuleRltSvc;
import com.uino.dao.util.ESUtil;
import com.uino.service.permission.microservice.IUserSvc;
import com.uino.util.sys.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DiagramProcessSvcImpl implements DiagramProcessSvc {

    @Autowired
    ESDiagramSvc esDiagramSvc;
    @Autowired
    ESDiagramDao esDiagramDao;
    @Autowired
    ESDiagramApiClient esDiagramApiClient;
    @Autowired
    IEamArtifactSvc eamArtifactSvc;
    @Autowired
    FlowableFeign flowableFeign;
    @Autowired
    EamCategorySvc eamCategorySvc;
    @Autowired
    ProcessDiagramSvc processDiagramSvc;
    @Autowired
    AssetWarehouseDirDao assetWarehouseDirDao;
    @Autowired
    DiagramApproveRltSvc diagramApproveRltSvc;
    @Autowired
    DiagramApproveRltDao diagramApproveRltDao;
    @Autowired
    IBmMultiModelHierarchySvc multiModelHierarchySvc;
    @Autowired
    ESRoleModuleRltSvc rmRltSvc;
    @Autowired
    IRoleApiSvc iRoleApiSvc;
    @Autowired
    PlanDesignInstanceDao planDesignInstanceDao;
    @Autowired
    BmConfigSvc bmConfigSvc;
    @Autowired
    private IOrgApiSvc orgService;
    @Autowired
    private IUserSvc userSvc;
    @Autowired
    private EamDiagramRelationSysService diagramRelationSysService;
    @Autowired
    private ICISwitchSvc ciSwitchSvc;
    @Autowired
    private DiagramReviewInfoDao diagramReviewInfoDao;

    @Value("${http.resource.space}")
    private String httpResouceUrl;

    @Value("${is.gt.environment:false}")
    private Boolean isGtEnvironment;


    @Override
    public ApproveParam submit(String diagramId, Long dirId, String desc, List<Long> modelDirIds, Boolean isChildProcess, AssetType assetType) {
        return this.submit(diagramId, dirId, desc, modelDirIds, isChildProcess, assetType, "");
    }

    @Override
    public ApproveParam submit(String diagramId, Long dirId, String desc, List<Long> modelDirIds, Boolean isChildProcess, AssetType assetType, String taskId) {
        // 获取开启审批流程需要的参数
        log.info("########## 当前处理批次参数 diagramId：【{}】，dirId：【{}】，desc：【{}】，modelDirIds：【{}】，isChildProcess：【{}】，assetType：【{}】",
                diagramId, dirId, desc, JSONObject.toJSONString(modelDirIds), isChildProcess, JSONObject.toJSONString(assetType));
        ApproveParam param = new ApproveParam();

        // 查询审批类型
        ESDiagramDTO appeoveDiagram = new ESDiagramDTO();
        EamCategory approveDirInfo = new EamCategory();
        param.setTargetDirId(dirId);
        param.setDesc(desc);
        param.setTaskId(taskId);
        List<Long> approveDiagramIds = new ArrayList<>();
        List<EamCategory> privateDirInfos = new ArrayList<>();
        List<ESDiagram> approveDiagramInfoList = new ArrayList<>();
        Long id = null;


        /*
         *  一.校验当前提交数据是否已经在流程中：
         *  单图提交校验情况，传参为单图ID：（获取视图本身的状态，目前视图提交可以从《我的空间》《待办》和《方案》开启，需要注意方案衔接流程的情况）
         *       一.普通视图 只需要查询当前普通视图流程状态
         *            流程中：（flowStatus = 2）-直接返回流程中的businessKey
         *            驳回：（flowStatus = 1）-数据需要获取到businessKey衔接流程
         *       二.模型单图
         *            流程中：
         *               1.处于模型目录的某次提交的流程中（isSingle = false，diagramId包含在approveDiagramIds中）抛出异常，重新选择
         *               2.处于模型单图提交的流程中（isSingle = true）直接返回流程中的businessKey
         *            驳回：
         *               1.当前视图的驳回数据是存在目录提交驳回中，抛出异常，重新选择
         *               2.本身的模型单图提交被驳回 获取到businessKey衔接流程
         *  模型目录提交校验情况，传参为目录IDS：（目前目录提交可以从《我的空间》和《待办》开启，需要注意待办衔接流程的情况）
         *       ******正常情况下流程中的目录审批不会触发二次审批 驳回的数据只会在待办中触发 判断当前提交是否为驳回数据******
         *       驳回数据：直接衔接流程 需要注意 提交批次的视图数据以关联表为主
         *       非驳回数据（进行审批校验）：当前提交审批的数据中存在于流程中（视图的flowStatus = 1或2）数据：抛出异常，提示先结束流程
         *
         * */

        if (!BinaryUtils.isEmpty(diagramId)) {
            id = esDiagramSvc.queryDiagramInfoByEnergy(diagramId);
            appeoveDiagram = esDiagramSvc.queryDiagramInfoById(id, null, Boolean.TRUE);
            // 方案会可能会传入审批中的视图 进行一次过滤
            Long privateDirId = appeoveDiagram.getDiagram().getDirId();
            approveDirInfo = eamCategorySvc.getById(privateDirId, LibType.PRIVATE);
            if (!BinaryUtils.isEmpty(approveDirInfo)) {
                privateDirInfos.add(approveDirInfo);
            }
            Integer diagramFlowStatus = BinaryUtils.isEmpty(appeoveDiagram.getDiagram().getFlowStatus())?0:appeoveDiagram.getDiagram().getFlowStatus();
            if (!BinaryUtils.isEmpty(approveDirInfo) && approveDirInfo.getType() == CategoryTypeEnum.MODEL.val()) {
                log.info("########## 单图发布 模型视图流程审批");
                if (diagramFlowStatus == 2) {
                    log.info("########## 模型单图处于流程审批中");
                    List<DiagramApproveRlt> diagramApproveRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveDirInfo.getModelId(), approveDirInfo.getOwnerCode(), null, null, Lists.newArrayList(2), Boolean.FALSE);
                    for (DiagramApproveRlt rlt : diagramApproveRlts) {
                        if (rlt.getDEnergysList().contains(diagramId)) {
                            log.info("########## 当前审批的模型单图处于另一条模型审批中，正在进行的流程businessKey：【{}】", rlt.getId());
                            throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】处于流程审批中");
                        }
                    }
                    log.info("########## 模型单图与模型目录审批无交集");
                    List<DiagramApproveRlt> singleApproveRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveDirInfo.getModelId(), approveDirInfo.getOwnerCode(), null, diagramId, Lists.newArrayList(2), Boolean.TRUE);
                    if (singleApproveRlts.size() != 1) {
                        throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】审批流程异常，为获取到流程数据");
                    } else {
                        // 这里兼容一下方案子流程的情况 返回当前的流程 busiessKey
                        /*DiagramApproveRlt approveRlt = singleApproveRlts.get(0);
                        param.setBusinessKey(approveRlt.getId().toString());
                        param.setModelType(approveRlt.getModelType());
                        return param;*/
                        throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】处于流程审批中");
                    }
                }
                if (diagramFlowStatus == 1) {
                    log.info("########## 模型单图已被驳回，衔接上次审批节点");
                    List<DiagramApproveRlt> rejectRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveDirInfo.getModelId(), approveDirInfo.getOwnerCode(), null, null, Lists.newArrayList(1), Boolean.FALSE);
                    for (DiagramApproveRlt rlt : rejectRlts) {
                        if (rlt.getDEnergysList().contains(diagramId)) {
                            log.info("########## 当前审批的模型单图处于另一条模型审批中，正在进行的流程businessKey：【{}】", rlt.getId());
                            throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】处于流程审批中");
                        }
                    }
                    List<DiagramApproveRlt> rejectSingleRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveDirInfo.getModelId(), approveDirInfo.getOwnerCode(), null, diagramId, Lists.newArrayList(1), Boolean.TRUE);
                    if (rejectSingleRlts.size() != 1) {
                        throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】审批流程异常，为获取到流程数据");
                    } else {
                        DiagramApproveRlt approveRlt = rejectSingleRlts.get(0);
                        param.setBusinessKey(approveRlt.getId().toString());
                        param.setModelType(approveRlt.getModelType());
                        param.setFlowStatus(1);
                    }
                }
            } else {
                log.info("########## 单图发布 普通视图流程审批");
                param.setBusinessKey(diagramId);
                if (diagramFlowStatus == 2) {
                    log.info("########## 视图处于流程审批中");
                    throw new ServerException("视图【" + appeoveDiagram.getDiagram().getName() + "】已提交审批，请勿重复提交");
                }
                if (diagramFlowStatus == 1) {
                    log.info("########## 视图已被驳回，衔接上次审批节点");
                    param.setFlowStatus(1);
                }
            }
        } else {
            log.info("########## 模型目录发布 模型目录流程审批");
            String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
            // 模型目录审批校验 一.发布层级下不能存在审批中的视图
            privateDirInfos = eamCategorySvc.getByIds(modelDirIds, LibType.PRIVATE);
            if (BinaryUtils.isEmpty(privateDirInfos)) throw new ServerException("提交模型目录数据异常");
            Integer categoryFlowStatus = 0;
            // 获取模型目录驳回的记录 判断是否有本次提交的
            List<DiagramApproveRlt> rejectRlts = diagramApproveRltSvc.queryApproveRltByInfo(privateDirInfos.get(0).getModelId(), loginCode, null, null, Lists.newArrayList(1), Boolean.FALSE);
            if (!BinaryUtils.isEmpty(rejectRlts)) {
                for (DiagramApproveRlt rlt : rejectRlts) {
                    List<Long> oldList = rlt.getApprovelDirList();
                    oldList.sort((o1, o2) -> o2.compareTo(o1));
                    modelDirIds.sort((o1, o2) -> o2.compareTo(o1));
                    if (oldList.equals(modelDirIds)) {
                        log.info("########## 当前审批模型目录获取到驳回数据,衔接驳回流程 old：【{}】,new：【{}】",
                                JSONObject.toJSONString(oldList), JSONObject.toJSONString(modelDirIds));
                        categoryFlowStatus = 1;
                        param.setBusinessKey(rlt.getId().toString());
                        param.setDesc(desc);
                        param.setTargetDirId(dirId);
                        param.setDiagramIds(rlt.getDiagramIdList());
                        param.setDEnergys(rlt.getDEnergysList());
                        param.setModelId(rlt.getModelId());
                        break;
                    }
                }
            }
            if (categoryFlowStatus != 1) {
                approveDiagramInfoList = esDiagramSvc.selectByDirIds(modelDirIds, null, loginCode, Lists.newArrayList(0));
                for (ESDiagram diagram : approveDiagramInfoList) {
                    if (!BinaryUtils.isEmpty(diagram.getFlowStatus()) && diagram.getFlowStatus() != 0) {
                        log.info("########## 模型目录存在流程未结束的视图");
                        throw new ServerException("当前审批目录下存在未完成的视图审批，请先完成已有审批流程");
                    }
                }
            }
            param.setFlowStatus(categoryFlowStatus);
        }

        // 二.提交审批
        if (AssetType.DIAGRAM.equals(assetType)) {
            // 普通视图审批
            param.setViewType(BinaryUtils.isEmpty(appeoveDiagram.getDiagram().getViewType()) ? 0L : Long.valueOf(appeoveDiagram.getDiagram().getViewType()));
            param.setApproveDirType(BinaryUtils.isEmpty(approveDirInfo) ? 1 : approveDirInfo.getType());
            param.setDiagramName(appeoveDiagram.getDiagram().getName());
            //默认视图创建者为流程发起人，如果是非视图创建人提交的审批（协作者发布权限），则默认协作者为流程发起人
            String ownerCode = appeoveDiagram.getDiagram().getOwnerCode();
            TaskFromWorkflowContextValue contextValue = TaskFromWorkflowContext.getContext();
            if (contextValue != null && StringUtils.isNotBlank(contextValue.getStartUserLoginCode())) {
                ownerCode = contextValue.getStartUserLoginCode();
            }
            param.setOwnerCode(ownerCode);
            param.setDiagramId(appeoveDiagram.getDiagram().getId());
            param.setFlowStatus(BinaryUtils.isEmpty(appeoveDiagram.getDiagram().getFlowStatus()) ? 0 : appeoveDiagram.getDiagram().getFlowStatus());
            param.setBusinessKey(diagramId);
            param.setDEnergy(diagramId);
            param.setProcessDefinitionKey(FlowableConstant.GT_DIAGRAM_APPROVE);
            param.setProcessInstanceName(getGTDiagramProcessInstanceName(appeoveDiagram.getDiagram()));
            approveDiagramIds.add(appeoveDiagram.getDiagram().getId());
            param.setDiagramIds(approveDiagramIds);
        } else {
            String ownerCode = privateDirInfos.get(0).getOwnerCode();
            if (!BinaryUtils.isEmpty(modelDirIds)) {
                // 模型目录审批
                param.setIsSingle(Boolean.FALSE);
                if (param.getFlowStatus() == 0) {
                    privateDirInfos = eamCategorySvc.getByIds(modelDirIds, LibType.PRIVATE);
                    privateDirInfos.sort(Comparator.comparing(EamCategory::getDirLvl));
                    List<Long> approveDirIds = privateDirInfos.stream().map(EamCategory::getId).collect(Collectors.toList());
                    // 获取目录下的所有视图数据
                    List<String> approveEnergys = new ArrayList<>();
                    for (ESDiagram esDiagram : approveDiagramInfoList) {
                        approveDiagramIds.add(esDiagram.getId());
                        approveEnergys.add(esDiagram.getDEnergy());
                    }

                    EamCategory rootCategory = privateDirInfos.get(0);
                    param.setApproveRootDirId(rootCategory.getId());
                    param.setModelId(rootCategory.getModelId());
                    param.setDEnergys(approveEnergys);
                    param.setDiagramIds(approveDiagramIds);
                    param.setProcessInstanceName(rootCategory.getDirName() + "审批流程");
                    param.setReleaseParamDirList(approveDirIds);
                }
            } else {
                // 模型单图审批
                param.setIsSingle(Boolean.TRUE);
                param.setApproveRootDirId(approveDirInfo.getId());
                // param.setReleaseParamDirList(); 这个不需要存
                param.setModelId(approveDirInfo.getModelId());
                param.setDEnergy(diagramId);
                param.setDiagramId(id);
                param.setDiagramIds(Collections.singletonList(id));
                if (!BinaryUtils.isEmpty(appeoveDiagram.getDiagram().getFlowStatus())) {
                    param.setFlowStatus(appeoveDiagram.getDiagram().getFlowStatus());
                }
                param.setProcessInstanceName(appeoveDiagram.getDiagram().getName() + "审批流程");
                param.setReleaseParamDirList(Collections.singletonList(approveDirInfo.getId()));
                approveDiagramIds.add(id);
            }
            param.setApproveDirType(CategoryTypeEnum.MODEL.val());
            param.setOwnerCode(ownerCode);
            EamMultiModelHierarchy modelInfo = multiModelHierarchySvc.getModelById(param.getModelId());
            if (BinaryUtils.isEmpty(modelInfo)) throw new ServerException("当前审批数据所属模型树异常");
            param.setModelType(modelInfo.getModelType());

            // 业务流程最后在关联表创建关联数据
            this.generateApproveRlt(param);
            param.setProcessDefinitionKey(isChildProcess ? FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE :
                    FlowableConstant.MODEL_DEFINITION_KEY);
        }
        if (!isChildProcess) {
            // 开启审批流程 如果属于子流程，跟随主流程进行审批 不需要单独开启
            this.startApproveProcess(param);
        } else {
            if (!BinaryUtils.isEmpty(param.getTaskId())) {
                this.startApproveProcess(param);
            }
        }
        // 修改视图状态为审批中
        esDiagramSvc.updateFlowStatusByIds(param.getDiagramIds(), 2);
        return param;
    }

    private String getGTDiagramProcessInstanceName(ESDiagramInfoDTO diagram) {
        String baseName = "架构图审核";
        String artifactName = "";
        String bindAssertName = "";
        //制品视图
        if (diagram.getDiagramSubType() != null
                && diagram.getDiagramSubType() == 2
                && StringUtils.isNotBlank(diagram.getViewType())) {
            //查制品
            EamArtifactVo artifactVo = eamArtifactSvc.queryArtifact(Long.valueOf(diagram.getViewType()));
            if (artifactVo != null) {
                artifactName = artifactVo.getArtifactName();
            }
            // 关联资产名称
            EamDiagramRelationSys diagramRelation = diagramRelationSysService.getEamDiagramRelationSys(diagram.getDEnergy());
            if (diagramRelation != null) {
                List<ESCIInfo> ciList = ciSwitchSvc.getCiByCodes(Collections.singletonList(diagramRelation.getEsSysId()), null, LibType.DESIGN);
                if (!CollectionUtils.isEmpty(ciList)) {
                    ESCIInfo ci = ciList.get(0);
                    bindAssertName = ci.getCiLabel().replace("[", "").replace("]", "").replace("\"", "");
                }
            }
        }
        return StringUtils.isBlank(artifactName) && StringUtils.isBlank(bindAssertName) ?
                baseName : baseName.concat("-").concat(bindAssertName).concat(artifactName);
    }

    @Override
    public Boolean isExistDir(String businessKey, String processDefinitionKey) {
        // 获取流程节点信息
        Long releaseDirId = null;
        Long productId = null;
        if (processDefinitionKey.equals(FlowableConstant.MODEL_DEFINITION_KEY) ||
                processDefinitionKey.equals(FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE)) {
            log.info("######### 业务流程审批通过，校验发布位置 bussinessKey：【{}】", businessKey);
            DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(businessKey.toString()));
            if (!BinaryUtils.isEmpty(approveRlt)) {
                releaseDirId = approveRlt.getTargetDirId();
                productId = approveRlt.getModelId();
            }
        } else {
            log.info("######### IT视图审批第二节点审批通过，校验发布位置 diagramId：【{}】", businessKey);
            PorcessResponse porcess = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(businessKey, processDefinitionKey);
            Map<String, Object> routerVariables = porcess.getRouterVariables();
            if (!BinaryUtils.isEmpty(routerVariables)) {
                Object param = routerVariables.get("releaseDirId");
                if (!BinaryUtils.isEmpty(param)) {
                    releaseDirId = Long.valueOf(param.toString());
                    Object viewType = routerVariables.get("viewType");
                    if (!BinaryUtils.isEmpty(viewType)) {
                        productId = Long.valueOf(viewType.toString());
                    } else {
                        // 流程变量中未查到制品信息 一般不会有这种情况
                        ESDiagram esDiagram = esDiagramSvc.getEsDiagram(businessKey, 0);
                        productId = BinaryUtils.isEmpty(esDiagram.getViewType()) ? 0L : Long.valueOf(esDiagram.getViewType());
                    }
                }
            }
        }
        if (BinaryUtils.isEmpty(releaseDirId)) {
            log.info("######### 流程变量中未查询到发布位置信息 businessKey：【{}】", businessKey);
            throw new BinaryException("流程变量中发布位置缺失！");
        }

        // 判断发布位置是否存在
        EamCategory designDirInfo = eamCategorySvc.getById(releaseDirId, LibType.DESIGN);
        if (BinaryUtils.isEmpty(designDirInfo)) {
            log.info("######### 未查询到设计库仓库信息 releaseDirId：【{}】", releaseDirId);
            return false;
        }
        // 判断根目录资产权限
        String dirPath = designDirInfo.getDirPath();
        String[] dirIds = dirPath.split("#");
        Long rootDirId = Long.valueOf(dirIds[1]);
        AssetWarehouseDir sysModile = assetWarehouseDirDao.getById(rootDirId);
        if (BinaryUtils.isEmpty(sysModile)) {
            // 根目录丢失
            log.info("######### 未查询到设计库仓库根目录信息 rootDirId：【{}】", rootDirId);
            return false;
        }
        Set<Long> productIds = processDefinitionKey.equals(FlowableConstant.DIAGRAM_DEFINITION_KEY) ?
                sysModile.getDiagramList().stream().map(TypeVo::getId).collect(Collectors.toSet()) : sysModile.getModelList().stream().map(TypeVo::getId).collect(Collectors.toSet());

        if (!BinaryUtils.isEmpty(productIds) && !productIds.contains(productId)) {
            // 视图无存放权限
            log.info("######### 当前审批数据类型无法存放与选择仓库下 rootDirId：【{}】，artifactId：【{}】", rootDirId, productId);
            return false;
        }
        return true;
    }

    @Override
    public void terminateProcess(String processInstanceId, String reason, String businessKey) {
        log.info("########## 发起终止本次流程请求，processInstanceId：【{}】，businessKey：【{}】", processInstanceId, businessKey);
        flowableFeign.terminateProcessInstanceById(processInstanceId, reason);
        log.info("########## 终止流程成功");
        // 修改视图状态
        ESDiagram esDiagram = esDiagramSvc.getEsDiagram(businessKey, 0);
        if (BinaryUtils.isEmpty(esDiagram)) {
            throw new BinaryException("审批视图不存在");
        }
        esDiagramSvc.updateFlowStatusByIds(Collections.singletonList(esDiagram.getId()), 0);
        log.info("########## 视图状态回退成功，流程终止成功，diagramId：【{}】", esDiagram.getDEnergy());
    }

    @Override
    public CategoryNode queryApproveModelInfoByBusinessKey(String businessKey) {
        DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(businessKey));
        if (BinaryUtils.isEmpty(approveRlt)) {
            throw new ServerException("流程ID：【" + businessKey + "】为获取到审批信息");
        }
        Long modelId = approveRlt.getModelId();
        Long approveRootDirId = approveRlt.getApproveRootDirId();
        List<Long> approvelDirList = approveRlt.getApprovelDirList();
        String ownerCode = approveRlt.getOwnerCode();
        List<Long> diagramIdList = approveRlt.getDiagramIdList();
        Boolean isSingle = approveRlt.getIsSingle();

        // 模型根节点目录信息
        EamCategory rootDirInfo = eamCategorySvc.getModelRoot(modelId, ownerCode, LibType.PRIVATE);

        // 处理跳级审批类型的提交
        List<EamCategory> approvelDirInfoList = eamCategorySvc.getByIds(approvelDirList, LibType.PRIVATE);
        Set<Long> approvePathIds = new HashSet<>();
        for (EamCategory approvelDirInfo : approvelDirInfoList) {
            String dirPath = approvelDirInfo.getDirPath();
            // List<String> dirPaths = Arrays.asList(dirPath.split("#")).stream().filter(e -> BinaryUtils.isEmpty(e)).collect(Collectors.toList());
            List<Long> dirPaths = Arrays.stream(dirPath.split("#")).filter(e -> !BinaryUtils.isEmpty(e)).map(e -> Long.valueOf(e)).collect(Collectors.toList());
            approvePathIds.addAll(dirPaths);
        }
        List<EamCategory> allModelDirList = eamCategorySvc.selectByModelId(modelId, LibType.PRIVATE, ownerCode);
        // 模型目录下的审批视图
        List<ESDiagram> esDiagramInfo = esDiagramDao.getListByQuery(QueryBuilders.termsQuery("id", diagramIdList));
        List<SimpDiagramInfo> simpDiagrams = EamUtil.copy(esDiagramInfo, SimpDiagramInfo.class);
        simpDiagrams.forEach(simp -> {
            simp.setIcon1(httpResouceUrl + simp.getIcon1());
        });
        Map<Long, List<SimpDiagramInfo>> diagramDirGroup = simpDiagrams.stream().collect(Collectors.groupingBy(SimpDiagramInfo::getDirId));
        allModelDirList.sort(Comparator.comparing(EamCategory::getId));

        List<CategoryNode> nodes = new ArrayList<>();
        for (EamCategory modelDir : allModelDirList) {
            if(!approvePathIds.contains(modelDir.getId())){
                continue;
            }
            CategoryNode node = EamUtil.copy(modelDir, CategoryNode.class);
            if (!BinaryUtils.isEmpty(diagramDirGroup.get(node.getId()))) {
                List<SimpDiagramInfo> simpDiagramInfos = diagramDirGroup.get(node.getId());
                simpDiagramInfos.forEach(simp -> {
                    if (!BinaryUtils.isEmpty(modelDir.getDiagramId()) && simp.getDEnergy().equals(modelDir.getDiagramId())) {
                        simp.setIsMain(Boolean.TRUE);
                    } else {
                        simp.setIsMain(Boolean.FALSE);
                    }
                });
                node.setEsDiagramList(simpDiagramInfos);
            }
            nodes.add(node);
        }
        Map<Long, List<CategoryNode>> listMap = nodes.stream().collect(Collectors.groupingBy(CategoryNode::getParentId));
        for (CategoryNode node : nodes) {
            node.setChildren(listMap.get(node.getId()));
        }
        List<CategoryNode> modelNodes = nodes.stream().filter(node -> Objects.equals(node.getId(), approveRootDirId)).collect(Collectors.toList());
        CategoryNode rootDirNode = EamUtil.copy(rootDirInfo, CategoryNode.class);
        rootDirNode.setChildren(modelNodes);
        rootDirNode.setFlowStatus(approveRlt.getFlowStatus());
        return rootDirNode;
    }

    @Override
    public Map<String, Object> queryApprovePath(String businessKey, String processDefinitionKey) {
        Map<String, Object> data = new HashMap<>();
        Boolean existDir = this.isExistDir(businessKey, processDefinitionKey);
        data.put("pushType", processDefinitionKey.equals(FlowableConstant.DIAGRAM_DEFINITION_KEY) ? AssetType.DIAGRAM : AssetType.MODEL);
        if (!existDir) {
            return data;
        }
        Long dirId =  null;
        String desc = "";
        if (processDefinitionKey.equals(FlowableConstant.MODEL_DEFINITION_KEY) ||
                processDefinitionKey.equals(FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE)) {
            DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(businessKey));
            desc = approveRlt.getReleaseDesc();
            dirId = approveRlt.getTargetDirId();
        } else {
            PorcessResponse porcessResponse = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(businessKey, processDefinitionKey);
            Map<String, Object> routerVariables = porcessResponse.getRouterVariables();
            Object param = routerVariables.get("releaseDirId");
            dirId = Long.valueOf(param.toString());
            if (!BinaryUtils.isEmpty(routerVariables.get("releaseDesc"))) {
                desc = routerVariables.get("releaseDesc").toString();
            }
        }
        data.put("dirId", dirId);
        data.put("desc", desc);

        EamCategory designInfo = eamCategorySvc.getById(dirId, LibType.DESIGN);
        String dirPath = designInfo.getDirPath();
        String[] moduleDirIds = dirPath.split("#");
        Long rootDirId = Long.valueOf(moduleDirIds[1]);
        AssetWarehouseDir sysModule = assetWarehouseDirDao.getById(rootDirId);


        String[] dirIds = dirPath.split("#");
        List<Long> ids = new ArrayList<>();
        for (String idStr : dirIds) {
            if (!BinaryUtils.isEmpty(idStr)) {
                ids.add(Long.valueOf(idStr));
            }
        }
        List<EamCategory> designCategory = eamCategorySvc.getByIds(ids, LibType.DESIGN);
        StringBuilder dirNamePath = new StringBuilder();
        designCategory = designCategory.stream().sorted(Comparator.comparing(EamCategory::getDirLvl)).collect(Collectors.toList());
        for (EamCategory design : designCategory) {
            dirNamePath.append("/").append(design.getDirName());
        }
        // 获取根目录名称
        data.put("dirNamePath", sysModule.getName() + dirNamePath);
        return data;
    }

    @Override
    public void pushApproveAsset(String businessKey, String processDefinitionKey, Long dirId, String desc, String taskId) {
        if (processDefinitionKey.equals(FlowableConstant.DIAGRAM_DEFINITION_KEY)
                || processDefinitionKey.equals(FlowableConstant.GT_DIAGRAM_APPROVE)) {
            // 衔接普通视图发布
            this.submit(businessKey, dirId, desc, null, Boolean.FALSE, AssetType.DIAGRAM);
        } else {
            // 衔接模型发布
            DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(businessKey));
            Boolean isSingle = approveRlt.getIsSingle();
            Boolean isChild = FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE.equals(processDefinitionKey) ? Boolean.TRUE : Boolean.FALSE;
            if (isSingle) {
                String approveDiagramId = approveRlt.getApproveDiagramId();
                // 单图 判断子流程
                if (isChild) {
                    this.submit(approveDiagramId, dirId, desc, null, isChild, AssetType.MODEL, taskId);
                } else {
                    this.submit(approveDiagramId, dirId, desc, null, isChild, AssetType.MODEL);
                }
            } else {
                // 目录
                List<Long> approvelDirList = approveRlt.getApprovelDirList();
                this.submit(null, dirId, desc, approvelDirList, isChild, AssetType.MODEL);
            }
        }
    }

    @Override
    public Boolean checkLocalStatus(Long dirId, String diagramId) {
        String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        if (!BinaryUtils.isEmpty(diagramId)) {
            BoolQueryBuilder bool = QueryBuilders.boolQuery();
            bool.must(QueryBuilders.termQuery("releaseDiagramId.keyword", diagramId));
            bool.must(QueryBuilders.termQuery("isOpen", 0));
            bool.must(QueryBuilders.termQuery("historyVersionFlag", 1));
            bool.must(QueryBuilders.termQuery("status", 1));
            bool.must(QueryBuilders.termQuery("dataStatus", 1));
            bool.must(QueryBuilders.termQuery("ownerCode.keyword", loginCode));
            bool.must(QueryBuilders.termsQuery("flowStatus", Lists.newArrayList(1,2)));
            List<ESDiagram> listByQuery = esDiagramDao.getListByQuery(bool);
            return BinaryUtils.isEmpty(listByQuery) ? Boolean.FALSE : Boolean.TRUE;
        }
        if (!BinaryUtils.isEmpty(dirId)) {
            EamCategory checkDirInfo = eamCategorySvc.getById(dirId, LibType.DESIGN);
            Long modelId = checkDirInfo.getModelId();
            List<EamCategory> privateCategories = eamCategorySvc.selectByModelId(modelId, LibType.PRIVATE, loginCode);
            if (!BinaryUtils.isEmpty(privateCategories)) {
                EamCategory privateCheckDirInfo = new EamCategory();
                String ciCode = checkDirInfo.getCiCode();
                for (EamCategory eamCategory : privateCategories) {
                    if (eamCategory.getCiCode().equals(ciCode)) {
                        privateCheckDirInfo = eamCategory;
                    }
                }
                if (!BinaryUtils.isEmpty(privateCheckDirInfo)) {
                    String id = privateCheckDirInfo.getId().toString();
                    List<Long> lowerLvl = privateCategories.stream().filter(e -> e.getDirPath().contains(id)).map(EamCategory::getId).collect(Collectors.toList());
                    if (!BinaryUtils.isEmpty(lowerLvl)) {
                        List<ESDiagram> esDiagrams = esDiagramSvc.selectByDirIds(lowerLvl, null, loginCode, Lists.newArrayList(0));
                        for (ESDiagram esDiagram : esDiagrams) {
                            if (!BinaryUtils.isEmpty(esDiagram.getFlowStatus()) && esDiagram.getFlowStatus() != 0) {
                                return Boolean.TRUE;
                            }
                        }
                    }
                }
            }

        }
        return Boolean.FALSE;
    }

    @Override
    public Boolean rollBackApproveData(String planBusinessKey, Integer rollBackStatus) {
        // 获取子流程关联信息
        if (BinaryUtils.isEmpty(planBusinessKey)) {
            return Boolean.TRUE;
        }
        log.info("############ 开启子流程回滚：参数 方案businessKey【{}】，rollBackStatus【{}】",
                planBusinessKey, rollBackStatus);
        PorcessResponse porcessResponse = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(planBusinessKey, FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE);
        if (BinaryUtils.isEmpty(porcessResponse)) {
            log.info("############# 根据businessKey未查询到新网业务方案审批流程数据");
            return Boolean.TRUE;
        }
        Map<String, Object> routerVariables = porcessResponse.getRouterVariables();
        Object childVariableList = routerVariables.get("childVariableList");
        List<Long> ids = new ArrayList<>();
        if (!BinaryUtils.isEmpty(childVariableList)) {
            List<ApproveParam> approveParams = JSONObject.parseArray(childVariableList.toString(), ApproveParam.class);
            for (ApproveParam param : approveParams) {
                ids.add(Long.valueOf(param.getBusinessKey()));
            }
        }
        if (BinaryUtils.isEmpty(ids)) {
            log.info("######### 根据businessKey未查询到子流程信息");
            return Boolean.TRUE;
        }
        log.info("######### 回滚子流程businessKeys：【{}】", JSONObject.toJSONString(ids));
        List<DiagramApproveRlt> approveRlts = diagramApproveRltSvc.getApproveRlts(ids);
        List<Long> diagramIds = new ArrayList<>();
        for (DiagramApproveRlt rlt : approveRlts) {
            diagramIds.addAll(rlt.getDiagramIdList());
        }
        if (BinaryUtils.isEmpty(diagramIds)) {
            return Boolean.TRUE;
        }
        diagramApproveRltSvc.batchChangeApproveRltFlowStatus(ids, rollBackStatus);
        esDiagramSvc.updateFlowStatusByIds(ids, rollBackStatus);
        return Boolean.TRUE;
    }

    @Override
    public List<DiagramApproveRlt> queryProcessRltByPlanOrModelKey(String planKey, String modelKey, Long rootDirId) {
        List<DiagramApproveRlt> data = new ArrayList<>();
        if (!BinaryUtils.isEmpty(planKey)) {
            PorcessResponse porcessResponse = flowableFeign.getProcessInstanceByBusinessIdAndProcessDefinitionKey(planKey, FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE);
            if (BinaryUtils.isEmpty(porcessResponse)) throw new ServerException("根据planKey未查询到流程信息");
            Map<String, Object> routerVariables = porcessResponse.getRouterVariables();
            Object childVariableList = routerVariables.get("childVariableList");
            if (BinaryUtils.isEmpty(childVariableList)) throw new ServerException("获取到的当前流程信息不存在childVariable信息");
            List<Long> ids = new ArrayList<>();
            List<ApproveParam> approveParams = JSONObject.parseArray(childVariableList.toString(), ApproveParam.class);
            for (ApproveParam param : approveParams) {
                ids.add(Long.valueOf(param.getBusinessKey()));
            }
            if (BinaryUtils.isEmpty(ids)) throw new ServerException("childVariable中不存在子流程信息");

            List<DiagramApproveRlt> approveRlts = diagramApproveRltSvc.getApproveRlts(ids);
            data.addAll(approveRlts);
        }
        if (!BinaryUtils.isEmpty(modelKey)) {
            DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(modelKey));
            if (BinaryUtils.isEmpty(approveRlt)) throw new ServerException("根据modelKey未查询到流程信息");
            data.add(approveRlt);
        }
        if (!BinaryUtils.isEmpty(rootDirId)) {
            SysUser currentUserInfo = SysUtil.getCurrentUserInfo();
            List<DiagramApproveRlt> approveRlts = diagramApproveRltSvc.queryApproveRltByInfo(null, currentUserInfo.getLoginCode(), rootDirId, null, new ArrayList<>(), null);
            if (BinaryUtils.isEmpty(approveRlts)) throw new ServerException("根据rootDirId未查询到流程信息");
            data.addAll(approveRlts);
        }
        return data;
    }

    @Override
    public List<DiagramApproveRlt> queryProcessRltByRootDiagramId(String diagramId, String ownerCode) {
        List<DiagramApproveRlt> diagramApproveRlts = diagramApproveRltSvc.queryApproveRltByInfo(null, ownerCode, null, diagramId, null, Boolean.TRUE);
        return diagramApproveRlts;
    }

    @Override
    public Boolean manualChangeRltAndDiagramStatusInfoByKeys(List<Long> businessKeys, Integer flowStatus) {
        List<DiagramApproveRlt> approveRlts = diagramApproveRltSvc.getApproveRlts(businessKeys);
        List<Long> rltIds = new ArrayList<>();
        List<Long> diagramIds = new ArrayList<>();
        for (DiagramApproveRlt rlt : approveRlts) {
            rltIds.add(rlt.getId());
            diagramIds.addAll(rlt.getDiagramIdList());
        }
        diagramApproveRltSvc.batchChangeApproveRltFlowStatus(rltIds, flowStatus);
        esDiagramSvc.updateFlowStatusByIds(diagramIds, flowStatus);
        return Boolean.TRUE;
    }

    @Override
    public Boolean selectDataStatus(String businessKey, String processDefinitionKey) {
        if (processDefinitionKey.equals(FlowableConstant.DIAGRAM_DEFINITION_KEY)
                || processDefinitionKey.equals(FlowableConstant.GT_DIAGRAM_APPROVE)) {
            return queryDiagramStatus(Collections.singletonList(businessKey));
        } else if (processDefinitionKey.equals(FlowableConstant.PLAN_DEFINITION_KEY1) || processDefinitionKey.equals(FlowableConstant.PLAN_DEFINITION_KEY2)) {
            return queryPlanStatus(businessKey);
        } else if (processDefinitionKey.equals(FlowableConstant.MODEL_DEFINITION_KEY)) {
            return queryModelStatus(businessKey);
        } else {
            throw new ServerException("未获取到流程定义信息");
        }
    }

    private Boolean queryDiagramStatus(List<String> diagramIds) {
        List<ESDiagram> diagramInfos = esDiagramDao.getListByQuery(QueryBuilders.termsQuery("dEnergy.keyword", diagramIds));
        if (BinaryUtils.isEmpty(diagramInfos)) {
            return Boolean.TRUE;
        }
        for (ESDiagram esDiagram : diagramInfos) {
            if (0 == esDiagram.getStatus()) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    private Boolean queryPlanStatus(String planId) {
        PlanDesignInstance planById = planDesignInstanceDao.getById(Long.valueOf(planId));
        if (BinaryUtils.isEmpty(planById)) {
            return Boolean.TRUE;
        }
        if (planById.getStatus().equals("deleted")) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private Boolean queryModelStatus(String businessKey) {
        DiagramApproveRlt approveRlt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(businessKey));
        if (BinaryUtils.isEmpty(approveRlt)) {
            return Boolean.TRUE;
        }
        List<String> dEnergysList = approveRlt.getDEnergysList();
        if (BinaryUtils.isEmpty(dEnergysList)) {
            return Boolean.TRUE;
        }
        return queryDiagramStatus(dEnergysList);
    }



    /**
     *  开启审批流程
     * @param processDefinitionKey 流程定义
     * @param businessKey 业务主键
     * @param processInstanceName 流程实例名称
     * @param routerVariable 流程中的全局变量
     * @param taskId 流程ID 驳回后的审批需要传
     */
    private void startProcess(String processDefinitionKey, String businessKey, String processInstanceName, Map<String, Object> routerVariable, String taskId) {
        log.info("######### 开启审批 提交审批参数，processDefinitionKey【{}】，businessKey【{}】，processInstanceName【{}】，routerVariable：【{}】，taskId：【{}】",
                processDefinitionKey, businessKey, processInstanceName, JSONObject.toJSONString(routerVariable), taskId);
        if (BinaryUtils.isEmpty(taskId)) {
            String loginCode = SysUtil.getCurrentUserInfo().getLoginCode();
            ProcessRequest processReq = new ProcessRequest();
            processReq.setProcessDefinitionKey(processDefinitionKey);
            processReq.setOwner(loginCode);
            processReq.setBusinessKey(businessKey);
            processReq.setUserId(loginCode);
            processReq.setProcessInstanceName(processInstanceName);
            log.info("routerVariable:{}",routerVariable);
            processReq.setRouterVariables(routerVariable);
            PorcessResponse response = flowableFeign.startProcessBindAssignee(processReq);
            taskId = response.getTaskId();
        }
        // 执行流程
        TaskRequest taskReq = new TaskRequest();
        taskReq.setTaskId(taskId);
        taskReq.setRouterVariables(routerVariable);
        taskReq.setAction(FLOWACTION.ACCETP);
        flowableFeign.completeTask(taskReq);
        log.info("######### 视图 diagramId：【{}】成功流转到下一节点", businessKey);
    }

    /**
     *  开启审批流
     * @param param 审批流程所需参数
     */
    private void startApproveProcess(ApproveParam param) {
        try {
            String taskId = "";
            // routerVariable 流程中的全局变量
            Map<String, Object> routerVariable = new HashMap<>();
            // taskId 流程ID 驳回后的审批需要传
            List<String> nextUserIds = new ArrayList<>();
            if (param.getProcessDefinitionKey().equals(FlowableConstant.DIAGRAM_DEFINITION_KEY)) {
                // 普通视图审批流程（二级审批）
                routerVariable.put("diagramId", param.getDiagramId());
                routerVariable.put("dEnergy", param.getDEnergy());
                routerVariable.put("viewType", param.getViewType());
            } else if (param.getProcessDefinitionKey().equals(FlowableConstant.GT_DIAGRAM_APPROVE)) {
                routerVariable.put("diagramId", param.getDiagramId());
                routerVariable.put("dEnergy", param.getDEnergy());
                routerVariable.put("viewType", param.getViewType());
                //仅提交评审的时候,设置下级审批用户
                if (param.getFlowStatus() == 0) {
                    nextUserIds = queryDiagramApprovalUsers();
                }
            } else {
                // 模型审批流程也包括子流程（一级审批）
                // todo 好像不太需要存变量 先留个口吧。。。
                String diagramType = param.getModelType() == 1 ? ModelProcessTypeEnum.ENTERPRISE.val() : ModelProcessTypeEnum.BUSINESS.val();
                routerVariable.put("diagramType", diagramType);
            }
            if (param.getFlowStatus() == 1) {
                log.info("########### 获取当前驳回流程：【{}】的任务节点businessKey", param.getBusinessKey());
                if (param.getProcessDefinitionKey().equals(FlowableConstant.XW_BUSINESS_SCENARIO_APPROVE)) {
                    taskId = param.getTaskId();
                } else {
                    TaskResponse taskResponse = flowableFeign.getCurrentUserTask(param.getBusinessKey(), param.getProcessDefinitionKey(), param.getOwnerCode());
                    taskId = taskResponse.getTaskId();
                    // 国投视图判断是否是撤回操作之后的提交
                    if (param.getProcessDefinitionKey().equals(FlowableConstant.GT_DIAGRAM_APPROVE)){
                        // 判断历史流程中最新的是驳回还是撤回  如果是撤回添加nextUserIds
                        List<HistoryTaskResponse> historyTaskByCurrentProcessInstanceId = flowableFeign.getHistoryTaskByCurrentProcessInstanceId(taskResponse.getProcessInstanceId());
                        if (!CollectionUtils.isEmpty(historyTaskByCurrentProcessInstanceId)) {
                            historyTaskByCurrentProcessInstanceId = historyTaskByCurrentProcessInstanceId.stream()
                                    .filter(h -> !h.getVariables().get("pass").equals("autoClose")).collect(Collectors.toList());
                            //拿到最后一个
                            HistoryTaskResponse historyTaskResponse = historyTaskByCurrentProcessInstanceId.get(historyTaskByCurrentProcessInstanceId.size() - 1);
                            Object pass = historyTaskResponse.getVariables().get("pass");
                            if(pass != null && pass.equals("recall")){
                                nextUserIds = queryDiagramApprovalUsers();
                            }
                        }
                    }
                }
            }
            routerVariable.put("releaseDirId", param.getTargetDirId());
            routerVariable.put("releaseDesc", param.getDesc());
            // startProcess(ApproveCategory.IT_VIEW_ARTIFACT.processDefinitionKey, param.getDEnergy(), param.getDiagramName() + "审批流程", routerVariable, taskId);
            log.info("######### 开启审批 提交审批参数，processDefinitionKey【{}】，businessKey【{}】，processInstanceName【{}】，routerVariable：【{}】，taskId：【{}】",
                    param.getProcessDefinitionKey(), param.getBusinessKey(), param.getProcessInstanceName(), JSONObject.toJSONString(routerVariable), taskId);
            if (BinaryUtils.isEmpty(taskId)) {
                ProcessRequest processReq = new ProcessRequest();
                processReq.setProcessDefinitionKey(param.getProcessDefinitionKey());
                processReq.setOwner(param.getOwnerCode());
                processReq.setBusinessKey(param.getBusinessKey());
                processReq.setUserId(param.getOwnerCode());
                processReq.setProcessInstanceName(param.getProcessInstanceName());
                log.info("routerVariable:{}",routerVariable);
                processReq.setRouterVariables(routerVariable);
                PorcessResponse response = flowableFeign.startProcessBindAssignee(processReq);
                taskId = response.getTaskId();
                // 维护视图审批记录 视图流程的 businessKey 是视图id
                if (param.getProcessDefinitionKey().equals(FlowableConstant.GT_DIAGRAM_APPROVE)) {
                    initDiagramReviewInfo(param,response);
                }
            }
            // 执行流程
            TaskRequest taskReq = new TaskRequest();
            taskReq.setTaskId(taskId);
            taskReq.setRouterVariables(routerVariable);
            taskReq.setAction(FLOWACTION.ACCETP);
            if (param.getProcessDefinitionKey().equals(FlowableConstant.GT_DIAGRAM_APPROVE) && !CollectionUtils.isEmpty(nextUserIds)) {
                taskReq.setNextUserIds(org.apache.commons.lang3.StringUtils.join(nextUserIds, ","));
            }
            flowableFeign.completeTask(taskReq);
            log.info("######### 流程 businessKey：【{}】成功流转到下一节点", param.getBusinessKey());
        } catch (Exception e) {
            if (param.getProcessDefinitionKey().equals(FlowableConstant.GT_DIAGRAM_APPROVE)) {
                throw new BinaryException(e.getMessage());
            }
            if (param.getProcessDefinitionKey().equals(FlowableConstant.MODEL_DEFINITION_KEY)) {
                // 模型审批回退创建的审批关系数据 兼容驳回的回退情况
                diagramApproveRltSvc.changeApproveRltFlowStatus(Long.valueOf(param.getBusinessKey()), param.getFlowStatus());
                log.info("############### 关系数据回退状态修改成功 businessKey：【{}】，回滚状态：【{}】", param.getBusinessKey(), param.getFlowStatus());
            }
            TaskResponse currentUserTask = flowableFeign.getCurrentUserTask(param.getBusinessKey(), param.getProcessDefinitionKey(), param.getOwnerCode());
            if (!BinaryUtils.isEmpty(currentUserTask)) {
                // 若产生流程数据 清除
                flowableFeign.terminateProcessInstanceById(currentUserTask.getProcessInstanceId(), e.getMessage());
            }
            log.error("############### 开启流程异常 exception：" + e);
            throw new ServerException("开启审批流程异常，异常原因：【" + e.getMessage() + "】");
        }
    }
    private void initDiagramReviewInfo(ApproveParam param,PorcessResponse taskResponse) {
        //根据 流程id查询对应的流程审批记录
        TermQueryBuilder query = QueryBuilders.termQuery("processInstanceId.keyword", taskResponse.getProcessInstanceId());
        List<DiagramReviewInfo> listByQuery = diagramReviewInfoDao.getListByQuery(query);
        if(CollectionUtils.isEmpty(listByQuery)){
            // 流程发起人
            UserInfo userInfo = userSvc.getUserInfoByLoginCode(param.getOwnerCode());
            // 制品类型
            String viewTypeName = "-";
            if (param.getViewType() != null) {
                EamArtifactVo eamArtifactVo = eamArtifactSvc.queryArtifact(param.getViewType());
                if (eamArtifactVo != null) {
                    viewTypeName = eamArtifactVo.getArtifactName();
                }
            }
            List<String> submitterOrgName = new ArrayList<>();
            List<Long> submitterOrgId = new ArrayList<>();
            if (!CollectionUtils.isEmpty(userInfo.getOrgs())) {
                List<SysOrg> orgs = new ArrayList<>(userInfo.getOrgs());
                Iterator<SysOrg> iterator = orgs.iterator();
                while (iterator.hasNext()) {
                    SysOrg org = iterator.next();
                    submitterOrgName.add(org.getOrgAllLevelName());
                    submitterOrgId.add(org.getId());
                }
            }
            //新建审批记录
            DiagramReviewInfo diagramReviewInfo = new DiagramReviewInfo();
            diagramReviewInfo.setId(ESUtil.getUUID());
            diagramReviewInfo.setCreateTime(ESUtil.getNumberDateTime());
            diagramReviewInfo.setReviewName(param.getProcessInstanceName());
            diagramReviewInfo.setDiagramId(param.getDiagramId());
            diagramReviewInfo.setDiagramEnergy(param.getBusinessKey());
            diagramReviewInfo.setDiagramName(param.getDiagramName());
            diagramReviewInfo.setViewTypeName(viewTypeName);
            diagramReviewInfo.setState(DiagramReviewState.REVIEWING);
            diagramReviewInfo.setCreatorCode(userInfo.getLoginCode());
            diagramReviewInfo.setCreatorName(userInfo.getUserName());
            diagramReviewInfo.setModifierCode(userInfo.getLoginCode());
            diagramReviewInfo.setModifierName(userInfo.getUserName());
            diagramReviewInfo.setModifyTime(ESUtil.getNumberDateTime());
            diagramReviewInfo.setCreatorOrgNameList(submitterOrgName);
            diagramReviewInfo.setCreatorOrgIdList(submitterOrgId);
            diagramReviewInfo.setProcessInstanceId(taskResponse.getProcessInstanceId());
            diagramReviewInfoDao.saveOrUpdate(diagramReviewInfo);
        }
    }

    private List<String> queryDiagramApprovalUsers() {
        String configJson = bmConfigSvc.getConfigType("AXEA_CONFIG");
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject conf = JSON.parseObject(configJson, JSONObject.class);
        if (StringUtils.isBlank(conf.getString("diagramApproveConf"))) {
            throw new BinaryException("未查询到国投视图审批配置，请联系管理员");
        }
        JSONObject diagramApproveConf = JSON.parseObject(conf.getString("diagramApproveConf"));
        if (StringUtils.isBlank(diagramApproveConf.getString("mapping"))) {
            throw new BinaryException("未查询到国投视图审批-组织角色配置，请联系管理员");
        }
        if (StringUtils.isBlank(diagramApproveConf.getString("defaultApproveRole"))) {
            throw new BinaryException("未查询到国投视图审批-默认组织角色配置，请联系管理员");
        }
        String curUserLoginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        CSysUser cdt = new CSysUser();
        cdt.setLoginCodeEqual(curUserLoginCode);
        List<UserInfo> userInfos = userSvc.getUserInfoByCdt(cdt, true);
        if (CollectionUtils.isEmpty(userInfos)) {
            throw new BinaryException("未找到当前用户信息");
        }
        UserInfo user = userInfos.get(0);
        if (CollectionUtils.isEmpty(user.getOrgs())) {
            throw new BinaryException("当前用户暂无所属组织");
        }
        log.info("{}所属组织信息:{}", curUserLoginCode, JSON.toJSONString(user.getOrgs()));
        /**
         * 【【视图评审】评审角色判断逻辑优化】
         * https://www.tapd.cn/65990798/prong/stories/view/1165990798001128413
         */
        String mappingStr = diagramApproveConf.getString("mapping");
        Map<String, String> mapping = JSON.parseObject(mappingStr, Map.class);
        Set<String> roleNames = new HashSet<>();
        for (SysOrg org : user.getOrgs()) {
            String gtDeptId = getGtDetId(org);
            if (mapping.containsKey(gtDeptId)) {
                roleNames.add(mapping.get(gtDeptId));
            }
        }
        if (CollectionUtils.isEmpty(roleNames)) {
            roleNames.add(diagramApproveConf.getString("defaultApproveRole"));
        }
        List<SysUser> users = new ArrayList<>();
        //查角色下的用户
        for (String roleName : roleNames) {
            List<SysUser> userList = userSvc.getUserByRoleNameAndCount(roleName, 200);
            if (!CollectionUtils.isEmpty(userList)) {
                users.addAll(userList);
            }
        }
        if (CollectionUtils.isEmpty(users)) {
            log.error("角色{}下暂未配置用户", JSON.toJSONString(roleNames));
            throw new BinaryException("未获取到审批人信息，请联系系统管理员处理");
        }
        return users.stream().map(SysUser::getLoginCode).distinct().collect(Collectors.toList());
    }

    private String getGtDetId(SysOrg org) {
        log.info("组织备注信息包含信息格式gtDeptId+orgId{}",org.getRemark());
        if (isGtEnvironment) {
            String remark = org.getRemark();
            String firstPart = StringUtils.isNotEmpty(remark)?
                    remark.contains("-")?remark.substring(0,remark.indexOf("-")):org.getId().toString():org.getId().toString();
            return firstPart;
        }
        return org.getId().toString();
    }

    /**
     *  模型审批创建审批关联数据
     */
    public void generateApproveRlt(ApproveParam approveParam) {
        // 分情况处理模型的目录审批与模型单图审批
        DiagramApproveRlt cdt = new DiagramApproveRlt();
        if (approveParam.getIsSingle()) {
            // 单图审批校验
            if (approveParam.getFlowStatus() != 0) {
                // 驳回数据 衔接流程
                List<DiagramApproveRlt> diagramApproveRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveParam.getModelId(), approveParam.getOwnerCode(), null, approveParam.getDEnergy(), Lists.newArrayList(1, 2), Boolean.TRUE);
                if (diagramApproveRlts.size() != 1) {
                    log.error("######### 流程异常 【模型视图】审批数据未在关联表中查询到对应的关系数据，diagramId：【{}】", approveParam.getDEnergy());
                    throw new ServerException("流程数据异常，请联系管理员");
                }
                cdt = diagramApproveRlts.get(0);
                cdt.setFlowStatus(2);
                cdt.setReleaseDesc(approveParam.getDesc());
                cdt.setTargetDirId(approveParam.getTargetDirId());
            } else {
                // 新审批流程
                setDiagramRltInfo(cdt, approveParam);
            }
        } else {
            // 目录审批校验
            /*List<DiagramApproveRlt> diagramApproveRlts = diagramApproveRltSvc.queryApproveRltByInfo(approveParam.getModelId(), approveParam.getOwnerCode(), approveParam.getApproveRootDirId(), null, Lists.newArrayList(1), Boolean.FALSE);
            if (diagramApproveRlts.size() > 1) {
                log.error("######### 流程异常 【模型目录】审批数据未在关联表中查询到对应的关系数据，rootDirId：【{}】, approveDirIds：【{}】",
                        approveParam.getApproveRootDirId(), JSONObject.toJSONString(approveParam.getReleaseParamDirList()));
                throw new ServerException("流程数据异常，请联系管理员");
            }*/

            if (approveParam.getFlowStatus() == 0) {
                // 新审批流程
                setDiagramRltInfo(cdt, approveParam);
            } else {
                // 驳回数据 衔接流程
                cdt = diagramApproveRltSvc.getApproveRlt(Long.valueOf(approveParam.getBusinessKey()));
                cdt.setFlowStatus(2);
                cdt.setReleaseDesc(approveParam.getDesc());
                cdt.setTargetDirId(approveParam.getTargetDirId());
                // cdt.setApprovelDirList(approveParam.getReleaseParamDirList());
            }
        }

        Long businesskey = diagramApproveRltSvc.saveDiagramApproveRlt(cdt);
        approveParam.setBusinessKey(businesskey.toString());
        // approveParam.setFlowStatus(0);
    }

    /**
     *  设置关联表基本信息
     * @param cdt
     * @param approveParam
     */
    private void setDiagramRltInfo (DiagramApproveRlt cdt, ApproveParam approveParam) {
        if (approveParam.getIsSingle()) {
            cdt.setDEnergysList(Collections.singletonList(approveParam.getDEnergy()));
            cdt.setDiagramIdList(Collections.singletonList(approveParam.getDiagramId()));
            cdt.setApproveDiagramId(approveParam.getDEnergy());
        } else {
            cdt.setDEnergysList(approveParam.getDEnergys());
            cdt.setDiagramIdList(approveParam.getDiagramIds());
        }
        cdt.setFlowStatus(2);
        cdt.setApprovelDirList(approveParam.getReleaseParamDirList());
        cdt.setOwnerCode(approveParam.getOwnerCode());
        cdt.setModelId(approveParam.getModelId());
        cdt.setModelType(approveParam.getModelType());
        cdt.setTargetDirId(approveParam.getTargetDirId());
        cdt.setReleaseDesc(approveParam.getDesc());
        cdt.setApproveRootDirId(approveParam.getApproveRootDirId());
        cdt.setIsSingle(approveParam.getIsSingle());
    }
}
